from flask import Flask, session, g
import config
from exts import db, mail
from models.models import UserModel
from routers.qa import bp as qa_bp
from routers.auth import bp as auth_bp
from flask_migrate import Migrate

app = Flask(__name__)
# 绑定配置文件
app.config.from_object(config)

db.init_app(app)
mail.init_app(app)

migrate = Migrate(app, db)

app.register_blueprint(qa_bp)
app.register_blueprint(auth_bp)


# blueprint：用来做模块化的
# 电影、读书、音乐、xxx

# flask db init：只需要执行一次
# flask db migrate：将orm模型生成迁移脚本
# flask db upgrade：将迁移脚本映射到数据库中

# before_request/ before_first_request/ after_request
# hook


# 1. `@app.before_request` 装饰器定义了一个在每次请求之前都会执行的函数 `my_before_request()`。这个钩子函数的作用是在处理请求之前做一些准备工作，比如加载当前用户的详细信息。
#
#    - `session.get("user_id")` 从 session 中获取用户 ID。session 是一种在服务器端存储信息的方式，通常用来保持用户的登录状态。
#    - 如果 `user_id` 存在（即用户已登录），那么通过 `UserModel.query.get(user_id)` 查询数据库来获取该用户的完整对象。这里的 `UserModel` 应该是一个 ORM（对象关系映射）模型，它对应于数据库中的用户表。
#    - 使用 `setattr(g, "user", user)` 将查询到的用户对象设置为全局变量 `g` 的属性。`g` 是一个特殊的 Flask 对象，它的生命周期只存在于单个请求中，可以用来临时存储需要在整个请求过程中访问的数据。
#    - 如果 `user_id` 不存在，则将 `g.user` 设置为 `None`，表示没有登录用户。
#


@app.before_request
def my_before_request():
    user_id = session.get("user_id")
    if user_id:
        user = UserModel.query.get(user_id)
        setattr(g, "user", user)
    else:
        setattr(g, "user", None)


# 2. `@app.context_processor` 装饰器定义了一个上下文处理器 `my_context_processor()`。上下文处理器允许你向模板注入新的变量，这样在所有模板中都可以直接使用这些变量而无需手动传递。
#
#    - 这个上下文处理器返回一个字典，其中包含键 `"user"` 和值 `g.user`。这意味着在所有的模板中，你可以直接使用变量 `user` 来访问当前登录的用户对象。
# 保存用户信息
@app.context_processor
def my_context_processor():
    return {"user": g.user}


if __name__ == '__main__':
    app.run()
